有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java避免不可修改类的实例

假设我有两个类AB,这样B extends A,分别实现了方法getAgetB,它们具有相同的输入参数类型和返回类型(但名称不同)。在方法public static <T extends A> void print(T t)中,获取类型为AB的对象作为输入,如果对象类型为A,我想调用getA;如果对象类型为B,我想调用getB

如果我可以编辑AB的代码,我会让它们实现一个接口I,提供getValue()(在AB的实现中,getValue()分别调用getA()和getB(),然后从print()调用此方法。问题是:类A和类B不可修改。不能添加或更改任何方法,它们的类层次结构是固定的,我没有编写它们的代码,并且我没有访问源代码的权限

请注意,这也适用于以下情况:出于任何原因,我不想更改AB的代码

有没有不使用instanceof的方法可以做到这一点

下面是一个使用instanceof(坏!)的解决方案

public class Test {

    public static <T extends A> void print(T t){
        if (t instanceof B)
            System.out.println(((B)t).getB());
        else if (t instanceof A)
            System.out.println(t.getA());
    }

    public static class A {
        public String getA(){
            return "A";
        }
    }
    public static class B extends A {
        public String getB(){
            return "B";
        }
    }

}


共 (3) 个答案

  1. # 1 楼答案

    当您出于任何原因无法访问原始代码时,您最终不得不求助于instanceof之类的东西。在这些情况下,这本身并不坏——你的手被束缚住了

    我要做的是创建一个在你的T上泛化的包装类,给它一个getValue,按照你的建议用instanceof进行测试,并明确这个类存在的唯一原因是为使用a或B提供一个一致的接口。它仍然很粗糙,但你已经在一个地方包含了粗糙

  2. # 2 楼答案

    扩展Matt's answer,我将考虑使用这些类的Facade Pattern。这意味着您需要创建一个(或两个)单独的类来包装这两个类所需的功能。正如马特所建议的,这包括添加一个方法

    其好处是将应用程序与无法控制的API解耦。如果不需要原始库中的所有方法,还可以简化API

  3. # 3 楼答案

    谢谢你和@Matt。我想这绝对是最干净的方式。将提供不使用instanceof的完整代码:

    public static void main(String[] args){
        A a = new A();
        B b = new B();
        AWrapper aw = new AWrapper(a);
        BWrapper bw = new BWrapper(b);
        print(aw);
        print(bw);
    }
    
    public static void print(Wrapper t){
        System.out.println(t.getValue());
    }
    
    public static class A {
        public String getA(){
            return "A";
        }
    }
    public static class B extends A {
        public String getB(){
            return "B";
        }
    }
    
    public static interface Wrapper{
        public String getValue();
    }
    
    public static class AWrapper implements Wrapper{
        A a;
        public AWrapper (A a){
            this.a = a;
        }
        public String getValue(){
            return a.getA();
        }
    }
    
    public static class BWrapper implements Wrapper{
        B b;
        public BWrapper (B b){
            this.b = b;
        }
        public String getValue(){
            return b.getB();
        }
    }